import type { SchemaObject } from 'openapi-typescript'
import type { PluginOption } from 'vite'
import fs from 'node:fs/promises'
import { dirname, join } from 'node:path'
import process from 'node:process'
import openapiTS from 'openapi-typescript'

const prefixPath = join(__dirname, './prefix.ts')

async function getPrefixContent() {
  try {
    return await fs.readFile(prefixPath, 'utf-8')
  } catch (error) {
    console.error(`❌ 读取 prefix.ts 失败:`, error)
    return ''
  }
}

interface GenerateApiSchemaOptions {
  conf: {
    base: string
    services: {
      name: string
      url: string
    }[]
  }
  dir?: string
}

async function generateTypeFile(
  base: string,
  name: string,
  url: string,
  outputDir: string,
) {
  try {
    const rootDir = process.cwd()
    const filePath = join(rootDir, outputDir, `${name}.ts`)
    const dirPath = dirname(filePath)

    // 确保目录存在
    await fs.mkdir(dirPath, { recursive: true })

    // 读取 prefix.ts
    const prefix = await getPrefixContent()

    // 临时关闭 TLS 证书检查
    const originalTLS = process.env.NODE_TLS_REJECT_UNAUTHORIZED
    process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'

    const output = await openapiTS(`${base}${url}`, {
      version: 2,
      defaultNonNullable: true,
      additionalProperties: true,
      formatter(node: SchemaObject) {
        if (node?.format === 'int64') {
          return 'number | string'
        }
        if (node?.format === 'int32' && node.enum) {
          return `${node.enum.map((item: any) => Number(item)).join(' |')} | number`
        }
      },
    }).catch(console.warn)

    // 还原 TLS 设置
    process.env.NODE_TLS_REJECT_UNAUTHORIZED = originalTLS

    if (output && output.length > 195) {
      await fs.writeFile(filePath, prefix + output)
      console.log(`✅ 生成 TypeScript 类型文件: ${filePath}`)
    }
  } catch (error) {
    console.error(`❌ 生成 ${name}.ts 失败:`, error)
  }
}

export function generateApiSchema(
  options?: GenerateApiSchemaOptions,
): PluginOption {
  const defaultOptions: Omit<GenerateApiSchemaOptions, 'conf'> = {
    dir: 'src/apis/types/',
  }
  const opt = { ...defaultOptions, ...options }

  if (!opt.conf?.services?.length) {
    console.error('❌ 未提供 API JSON 文档地址')
    return
  }

  return {
    name: 'generate-api-schema',
    async options() {
      const { base, services } = opt.conf!

      for (const { name, url } of services) {
        await generateTypeFile(base, name, url, opt.dir!)
      }
    },
  }
}
